package org.erepublik.company.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;

import org.erepublik.company.Configuration;
import org.erepublik.company.ECountry;
import org.erepublik.company.EProductType;
import org.erepublik.company.JSONAble;
import org.erepublik.company.thread.ProductUpdater;
import org.erepublik.company.utils.Utils;
import org.json.JSONArray;
import org.json.JSONException;

/**
 * Klasa dostarczajaca oferty jedzenia z plikow JSON.
 * 
 * Obiekt sprawdza, czy nie ma nowszych ofert i zawsze zwraca najbardziej aktualne oferty
 *
 * @author Kacper Gorski 'Railman' railman85@gmail.com
 */
public abstract class JSONProductService<T extends JSONAble> {

    protected abstract T[] getProductFromJSONArray(JSONArray jsonArrayWithFood) throws JSONException;
    protected abstract T[] getEmptyTable();
    
    private long productScanTime;
    
	protected HashMap<ECountry, T[]> productMap = null;
	protected T[] allProducts = null;
	private String simpleName;

    protected EProductType productType;
	public JSONProductService(String simpleName, EProductType productType) {
	    this.simpleName = simpleName;
	    this.productType = productType;
	    setUp();
	}

	
	public JSONProductService(String simpleName) {
        this(simpleName, null);
        setUp();
    }
    protected void update() {
		long newFoodScannTime = ProductUpdater.getLastScanTime(simpleName);
	    if (newFoodScannTime>productScanTime) {
	        System.out.println("wykryto nowa liste jedzenia...");
	        setUp();
	    }
	}

    @SuppressWarnings("unchecked")
	public void setUp() {
   
        String foodUrl = getLastProductFile(simpleName);
        if (foodUrl==null) {
            productMap = new HashMap<ECountry, T[]>();
            for (int i=0; i < ECountry.values().length; i++) {
                productMap.put(ECountry.values()[i], getEmptyTable());
            }
            productMap.put(null, getEmptyTable());
            allProducts = getEmptyTable();
            productScanTime = 0;
            return;
        }
        try {
            productScanTime = ProductUpdater.getLastScanTime(simpleName);
            
            String jsonAsString = Utils.convertStreamToString( new FileInputStream(new File(foodUrl)) );
            JSONArray jsonArrayWithFood = new JSONArray(jsonAsString);
            T[] products = getProductFromJSONArray(jsonArrayWithFood);

            ArrayList<T>[] pProductsByCountry = new ArrayList[ECountry.values().length+1];
            for (int i=0; i < ECountry.values().length; i++)
                pProductsByCountry[i] = new ArrayList<T>();
            pProductsByCountry[ECountry.values().length] = new ArrayList<T>();
            
            allProducts = products;
            for (int i=0; i < products.length; i++) {
                if (products[i].getCountry()==null)
                    pProductsByCountry[ ECountry.values().length ].add(products[i]);
                else
                    pProductsByCountry[ products[i].getCountry().ordinal() ].add(products[i]);
            }

            HashMap<ECountry, T[]> foodMap = new HashMap<ECountry, T[]>();
            for (int i=0; i < ECountry.values().length; i++)
                foodMap.put(ECountry.values()[i], pProductsByCountry[i].toArray(getEmptyTable()));
            foodMap.put(null, pProductsByCountry[ECountry.values().length].toArray(getEmptyTable()));
            this.productMap = foodMap;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        
    }


    
    // sciezka do miejsca, gdzie przechowywane sa pliki z JSONami
	public String productDatabasePath = Configuration.databasePath + "/" + simpleName;



	public static String getLastProductFile(String simpleName) {
		
	    createDatabaseFolderIfNotExists(simpleName);
	    
		URL urlToDirectory = null;
		try {
			urlToDirectory = new URL("file://"+Configuration.databasePath + "/"+simpleName);
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		}

		try {
			File fildirectory = new File(urlToDirectory.toURI());
			File[] files = fildirectory.listFiles();
			ArrayList<String> fileList = new ArrayList<String>();
			for (File file : files) {
				if ( file.getPath().endsWith("-"+simpleName+".json") )
					fileList.add( file.getName() );
			}
			String[] fileTable = fileList.toArray(new String[0]);
			Arrays.sort(fileTable);
			if (fileTable.length==0)
			    return null;
			return Configuration.databasePath + "/"+ simpleName + "/" + fileTable[fileTable.length-1];
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}

	
    public String getMinutesSinceUpdate() {
        long time = new Date().getTime() - productScanTime;
        time /= 1000 * 60; 
        return time/60 + "h. "+time%60+"min.";
    }
	
	
	
	private static void createDatabaseFolderIfNotExists(String simpleName) {
	    File file_main = new File(Configuration.databasePath);
	    file_main.mkdir();
        File file_sub = new File(Configuration.databasePath + "/"+simpleName);
        file_sub.mkdir();
    }


}
